package io.youngledo.usb;

import io.youngledo.usb.connection.*;
import io.youngledo.usb.license.*;
import io.youngledo.usb.storage.*;
import io.youngledo.usb.task.*;
import io.youngledo.usb.util.FileUtils;
import io.youngledo.usb.util.IconManager;
import io.youngledo.usb.util.DialogUtils;
import io.youngledo.usb.security.CredentialManager;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/// 通用存储浏览器 - 多连接版本
/// 支持同时连接多个相同或不同类型的对象存储服务
///
public class UniversalStorageBrowser extends Application {

    // 核心管理器
    private ConnectionManager connectionManager;
    private I18nManager i18n;
    private NotificationManager notificationManager;
    private TaskManager taskManager;
    private TaskProgressDialog progressDialog;

    // UI组件
    private Stage primaryStage;
    private TreeView<TreeNodeData> storageTreeView;
    private TreeItem<TreeNodeData> treeRootItem;
    private TabPane connectionTabPane;
    private VBox notificationArea;
    private Label statusLabel;
    private Label websiteLabel;
    private Label docLabel;

    // 当前活动状态
    private StorageConnection activeConnection;
    private String activeBucket;

    // Tab管理
    private final Map<String, Tab> connectionTabs = new HashMap<>();
    private final Map<String, ConnectionTab> connectionTabContents = new HashMap<>();

    // 工具栏按钮
    private Button newConnectionButton;
    private Button closeConnectionButton;
    private Button taskManagerButton;

    @Override
    public void start(Stage primaryStage) {
        this.primaryStage = primaryStage;

        // 初始化管理器
        initializeManagers();

        // 异步设置窗口图标，避免阻塞UI初始化
        Platform.runLater(() -> setupWindowIcon(primaryStage));

        // 创建UI
        Scene scene = createMainScene();
        primaryStage.setScene(scene);
        primaryStage.setTitle(i18n.getString("app.title"));
        primaryStage.setWidth(1400);
        primaryStage.setHeight(900);
        primaryStage.setMinWidth(800);
        primaryStage.setMinHeight(600);

        // 确保窗口能够获得焦点
        primaryStage.setAlwaysOnTop(false); // 确保不是始终置顶
        primaryStage.setIconified(false);   // 确保不是最小化状态

        // 尝试强制获得焦点的关键设置
        primaryStage.setResizable(true);
        primaryStage.centerOnScreen();

        // 设置关闭事件
        primaryStage.setOnCloseRequest(event -> {
            connectionManager.disconnectAll();
            taskManager.shutdown();
            Platform.exit();
        });

        // 设置初始状态文本（在show之前）
        statusLabel.setText(i18n.getString("app.ready"));

        primaryStage.show();

        // 加载已保存的连接（在UI创建完成后）
        loadSavedConnections();

        // 确保窗口获得焦点
        Platform.runLater(() -> {
            // 临时设置为置顶以强制获得焦点，然后立即取消
            primaryStage.setAlwaysOnTop(true);
            primaryStage.toFront();
            primaryStage.requestFocus();

            // 立即取消置顶
            Platform.runLater(() -> {
                primaryStage.setAlwaysOnTop(false);
            });

            // 如果有场景，也确保场景获得焦点
            if (primaryStage.getScene() != null) {
                primaryStage.getScene().getRoot().requestFocus();
            }

            // 显示欢迎消息
            notificationManager.showInfo("欢迎使用通用存储浏览器！点击“新建连接”开始。");
        });

        // 基础焦点处理 - 简单有效
        Platform.runLater(() -> {
            primaryStage.toFront();
            primaryStage.requestFocus();
        });
    }

    /// 初始化管理器
    ///
    private void initializeManagers() {
        // 初始化许可证系统
        LicenseManager.initialize();

        i18n = I18nManager.getInstance();
        connectionManager = new ConnectionManager();
        notificationManager = new NotificationManager();
        notificationManager.setParentStage(primaryStage); // 设置父窗口，初始化异常列表对话框
        taskManager = TaskManager.getInstance();

        // 初始化进度对话框
        progressDialog = new TaskProgressDialog(primaryStage);
        progressDialog.setOnTaskCountChanged(this::updateTaskManagerButtonFromDialog);

        // 设置任务管理器回调
        setupTaskManagerCallbacks();
    }

    /// 设置任务管理器回调
    ///
    private void setupTaskManagerCallbacks() {
        taskManager.setOnTaskAdded(task -> {
            Platform.runLater(() -> {
                notificationManager.showInfo("任务已添加: " + task.getDescription());
                if (taskManagerButton != null) {
                    updateTaskManagerButtonText();
                }
            });
        });

        taskManager.setOnTaskCompleted(task -> {
            Platform.runLater(() -> {
                notificationManager.showSuccess("任务完成: " + task.getDescription());
                if (taskManagerButton != null) {
                    updateTaskManagerButtonText();
                }
                // Tabs automatically handle their own refresh via ConnectionTab
            });
        });

        taskManager.setOnTaskFailed(task -> {
            Platform.runLater(() -> {
                String errorMsg = task.getException() != null ?
                        task.getException().getMessage() : "未知错误";
                notificationManager.showError("任务失败: " + task.getDescription() + " - " + errorMsg);
                if (taskManagerButton != null) {
                    updateTaskManagerButtonText();
                }
            });
        });
    }

    /// 更新任务管理按钮文本
    ///
    private void updateTaskManagerButtonText() {
        TaskManager.TaskStatistics stats = taskManager.getStatistics();
        if (stats.activeTasks() > 0) {
            taskManagerButton.setText(String.format("任务管理 (%d)", stats.activeTasks()));
        } else {
            taskManagerButton.setText("任务管理");
        }
    }

    /// 从任务对话框更新任务管理按钮文本
    ///
    private void updateTaskManagerButtonFromDialog(int taskCount) {
        if (taskCount > 0) {
            taskManagerButton.setText(String.format("任务管理 (%d)", taskCount));
        } else {
            taskManagerButton.setText("任务管理");
        }
    }


    /// 设置窗口图标
    ///
    private void setupWindowIcon(Stage stage) {
        try {
            stage.getIcons().addAll(IconManager.createApplicationIcons());
        } catch (Exception e) {
            System.err.println("Failed to setup application icon: " + e.getMessage());
        }
    }

    /// 创建主界面
    ///
    private Scene createMainScene() {
        BorderPane root = new BorderPane();

        // 创建菜单栏
        MenuBar menuBar = createMenuBar();

        // 顶部工具栏
        ToolBar topToolBar = createTopToolBar();

        // 将菜单栏和工具栏组合到顶部
        VBox topContainer = new VBox();
        topContainer.getChildren().addAll(menuBar, topToolBar);

        // 中央分割面板
        SplitPane mainSplitPane = createMainSplitPane();

        // 底部状态栏
        HBox statusBar = createStatusBar();

        // 设置通知管理器的通知区域（在createLeftPanel中已创建）
        if (notificationArea != null) {
            notificationManager.setNotificationArea(notificationArea);
        }

        // 布局
        root.setTop(topContainer);
        root.setCenter(mainSplitPane);
        root.setBottom(statusBar);

        Scene scene = new Scene(root);

        // 加载扁平化CSS样式
        String css = getClass().getResource("/styles/application.css").toExternalForm();
        scene.getStylesheets().add(css);

        // 强制设置全局字体和颜色属性解决渲染问题
        root.setStyle(
                "-fx-font-family: 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; " +
                        "-fx-text-fill: #3c3c3c; " +
                        "-fx-base: #f5f5f7;"
        );

        return scene;
    }

    /// 创建菜单栏
    ///
    private MenuBar createMenuBar() {
        MenuBar menuBar = new MenuBar();

        // 检测操作系统，在macOS上使用系统菜单栏
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("mac")) {
            menuBar.setUseSystemMenuBar(true);
            // 延迟设置Desktop API处理器，让JavaFX完全初始化
            Platform.runLater(() -> {
                Platform.runLater(this::setupMacOSMenuHandlers);
            });
        }

        // 添加帮助菜单（所有平台统一）
        Menu helpMenu = new Menu("帮助");

        // 许可证信息
        MenuItem licenseInfoItem = new MenuItem("许可证信息");
        licenseInfoItem.setOnAction(e -> io.youngledo.usb.license.UpgradeDialog.showLicenseInfo());

        // 激活许可证
        MenuItem activateLicenseItem = new MenuItem("激活许可证...");
        activateLicenseItem.setOnAction(e -> io.youngledo.usb.license.LicenseActivationDialog.show());

        // 升级到专业版
        MenuItem upgradeItem = new MenuItem("升级到专业版");
        upgradeItem.setOnAction(e -> io.youngledo.usb.license.UpgradeDialog.showProFeatures());

        // 分隔符
        SeparatorMenuItem separator = new SeparatorMenuItem();

        // 关于
        MenuItem aboutItem = new MenuItem("关于");
        aboutItem.setOnAction(e -> showAboutDialog());

        helpMenu.getItems().addAll(
                licenseInfoItem,
                activateLicenseItem,
                upgradeItem,
                separator,
                aboutItem
        );

        menuBar.getMenus().add(helpMenu);

        return menuBar;
    }

    /// 设置macOS特定的菜单处理器
    ///
    private void setupMacOSMenuHandlers() {
        // 使用Java Desktop API来处理macOS特定的应用程序事件
        try {
            System.setProperty("apple.awt.application.name", "UniversalStorageBrowser");
            System.setProperty("com.apple.mrj.application.apple.menu.about.name", "UniversalStorageBrowser");

            if (java.awt.Desktop.isDesktopSupported()) {
                java.awt.Desktop desktop = java.awt.Desktop.getDesktop();

                // 处理"关于"菜单项
                if (desktop.isSupported(java.awt.Desktop.Action.APP_ABOUT)) {
                    desktop.setAboutHandler(e -> Platform.runLater(this::showAboutDialog));
                }

                // 处理退出菜单项
                if (desktop.isSupported(java.awt.Desktop.Action.APP_QUIT_HANDLER)) {
                    desktop.setQuitHandler((e, response) -> {
                        Platform.runLater(() -> {
                            connectionManager.disconnectAll();
                            taskManager.shutdown();
                            Platform.exit();
                        });
                        response.performQuit();
                    });
                }
            }
        } catch (Exception e) {
            // 如果Desktop API不可用，忽略异常
        }
    }

    /// 显示关于对话框
    ///
    private void showAboutDialog() {
        AboutDialog aboutDialog = new AboutDialog();
        aboutDialog.showAndWait();
    }

    /// 创建顶部工具栏
    ///
    private ToolBar createTopToolBar() {
        // 连接管理按钮
        newConnectionButton = new Button("新建连接");
        newConnectionButton.setTooltip(new Tooltip("创建新的存储连接"));

        closeConnectionButton = new Button("关闭连接");
        closeConnectionButton.setTooltip(new Tooltip("关闭当前活动连接"));
        closeConnectionButton.setDisable(true);

        taskManagerButton = new Button("任务管理");
        taskManagerButton.setTooltip(new Tooltip("查看和管理后台任务"));

        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);

        // 设置按钮事件
        setupToolBarEvents();

        return new ToolBar(
                newConnectionButton,
                closeConnectionButton,
                new Separator(),
                taskManagerButton,
                spacer
        );
    }

    /// 创建主分割面板
    ///
    private SplitPane createMainSplitPane() {
        SplitPane splitPane = new SplitPane();

        // 左侧存储树视图
        VBox leftPanel = createLeftPanel();

        // 右侧连接标签页
        connectionTabPane = createConnectionTabPane();

        splitPane.getItems().addAll(leftPanel, connectionTabPane);

        // 设置左侧面板的最大宽度限制，确保不会过宽
        leftPanel.setMaxWidth(300);

        // 在UI完全加载后设置分割位置
        Platform.runLater(() -> {
            splitPane.setDividerPositions(0.20); // 左侧占20%
        });

        return splitPane;
    }

    /// 创建连接标签页
    ///
    private TabPane createConnectionTabPane() {
        TabPane tabPane = new TabPane();
        tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.SELECTED_TAB);

        // 设置Tab关闭事件
        tabPane.getTabs().addListener((javafx.collections.ListChangeListener<Tab>) change -> {
            while (change.next()) {
                if (change.wasRemoved()) {
                    for (Tab removedTab : change.getRemoved()) {
                        handleTabClosed(removedTab);
                    }
                }
            }
        });

        // 设置Tab切换事件
        tabPane.getSelectionModel().selectedItemProperty().addListener((observable, oldTab, newTab) ->
                handleTabChanged(newTab)
        );

        return tabPane;
    }

    /// 为连接创建新的Tab
    ///
    private void createConnectionTab(StorageConnection connection) {
        String connectionId = connection.getId();

        // 如果Tab已存在，直接切换到该Tab
        if (connectionTabs.containsKey(connectionId)) {
            Tab existingTab = connectionTabs.get(connectionId);
            connectionTabPane.getSelectionModel().select(existingTab);
            return;
        }

        // 创建连接Tab内容
        ConnectionTab connectionTabContent = new ConnectionTab(connection, this);

        // 创建Tab标题，格式：图标 + 存储类型 + " - " + 连接名称
        String storageIcon = getStorageTypeIcon(connection.getConfig().type());
        String storageTypeName = connection.getConfig().type().getDisplayName();
        String tabTitle = storageIcon + " " + storageTypeName + " - " + connection.getDisplayName();

        Tab tab = new Tab(tabTitle);
        tab.setContent(connectionTabContent);
        tab.setClosable(true);

        // 设置Tab的用户数据为连接ID，便于后续查找
        tab.setUserData(connectionId);

        // 使用自定义关闭行为
        tab.setOnCloseRequest(event -> {
            // 显示确认对话框
            boolean confirmed = DialogUtils.showConfirmationDialog(
                    "关闭连接",
                    "确定要关闭此连接吗？",
                    "连接: " + connection.getDisplayName()
            );

            if (!confirmed) {
                // 用户取消，阻止关闭
                event.consume();
            }
        });

        // 保存映射关系
        connectionTabs.put(connectionId, tab);
        connectionTabContents.put(connectionId, connectionTabContent);

        // 添加到TabPane
        connectionTabPane.getTabs().add(tab);

        // 切换到新创建的Tab
        connectionTabPane.getSelectionModel().select(tab);

        // 更新活动连接
        activeConnection = connection;

        // 自动加载存储桶列表
        loadBucketsForConnectionTab(connectionTabContent);

        updateUI();
    }

    /// 处理Tab关闭事件
    ///
    private void handleTabClosed(Tab closedTab) {
        String connectionId = (String) closedTab.getUserData();
        if (connectionId == null) return;

        // 从映射中移除
        connectionTabs.remove(connectionId);
        ConnectionTab connectionTabContent = connectionTabContents.remove(connectionId);

        if (connectionTabContent != null) {
            StorageConnection connection = connectionTabContent.getConnection();

            // 检查是否为保存的连接
            if (connection.isSavedConnection()) {
                // 保存的连接：只断开连接，不从列表中移除
                connection.disconnect();
                notificationManager.showInfo("已断开连接，连接已保留在列表中");

                // 更新树视图中的显示状态
                updateSavedConnectionDisplayName(connection);
            } else {
                // 普通连接：完全移除
                removeConnectionFromTree(connection);
                connection.disconnect();
                connectionManager.removeConnection(connection.getId());
                notificationManager.showInfo("已断开连接");
            }
        }

        // 如果关闭的是当前活动连接，需要更新活动连接
        if (activeConnection != null && activeConnection.getId().equals(connectionId)) {
            // 尝试切换到其他Tab
            if (!connectionTabPane.getTabs().isEmpty()) {
                Tab firstTab = connectionTabPane.getTabs().getFirst();
                String firstConnectionId = (String) firstTab.getUserData();
                ConnectionTab firstConnectionTab = connectionTabContents.get(firstConnectionId);
                if (firstConnectionTab != null) {
                    activeConnection = firstConnectionTab.getConnection();
                } else {
                    activeConnection = null;
                }
            } else {
                activeConnection = null;
            }
            activeBucket = null;
        }

        updateUI();
    }

    /// 处理Tab切换事件
    ///
    private void handleTabChanged(Tab newTab) {
        if (newTab == null) {
            activeConnection = null;
            activeBucket = null;
            updateUI();
            return;
        }

        String connectionId = (String) newTab.getUserData();
        if (connectionId == null) return;

        ConnectionTab connectionTabContent = connectionTabContents.get(connectionId);
        if (connectionTabContent != null) {
            StorageConnection connection = connectionTabContent.getConnection();
            activeConnection = connection;
            activeBucket = connectionTabContent.getCurrentBucket();

            // 同步左侧树视图的选择
            syncTreeViewSelection(connection);

            updateUI();
        }
    }

    /// 同步左侧树视图的选择状态
    ///
    private void syncTreeViewSelection(StorageConnection connection) {
        for (TreeItem<TreeNodeData> storageTypeItem : treeRootItem.getChildren()) {
            for (TreeItem<TreeNodeData> connectionItem : storageTypeItem.getChildren()) {
                TreeNodeData connectionData = connectionItem.getValue();
                if (connectionData.isConnection() && connectionData.getConnection().equals(connection)) {
                    storageTreeView.getSelectionModel().select(connectionItem);
                    return;
                }
            }
        }
    }

    /// Tab相关的业务方法 - 由ConnectionTab调用
    /// 为指定Tab加载存储桶文件
    ///
    public void loadBucketFilesForTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();
        String bucketName = connectionTab.getCurrentBucket();

        if (!connection.isConnected() || bucketName == null) return;

        // 显示加载指示器
        connectionTab.showLoading();

        executeAsyncTask(
                "正在加载 " + bucketName + " 的文件...",
                () -> connection.getService().listObjects(bucketName, connection.getCurrentPrefix(), false),
                objects -> {
                    connectionTab.getAllFiles().setAll(objects);
                    connectionTab.getFilteredFiles().setAll(objects);
                    statusLabel.setText("已加载 " + objects.size() + " 个项目");
                    // 隐藏加载指示器
                    connectionTab.hideLoading();
                },
                exception -> {
                    statusLabel.setText("加载失败: " + exception.getMessage());
                    notificationManager.handleStorageException(exception, "加载文件列表");
                    // 隐藏加载指示器
                    connectionTab.hideLoading();
                }
        );
    }

    /// 为指定Tab导航返回上级目录
    ///
    public void navigateBackForTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();

        if (connection == null || currentBucket == null) {
            return;
        }

        String currentPrefix = connection.getCurrentPrefix();
        if (currentPrefix == null || currentPrefix.isEmpty()) {
            return; // 已经在根目录了
        }

        // 计算上级目录路径
        String newPrefix = "";
        if (!currentPrefix.equals("/")) {
            // 移除末尾的"/"
            if (currentPrefix.endsWith("/")) {
                currentPrefix = currentPrefix.substring(0, currentPrefix.length() - 1);
            }

            // 找到上级目录
            int lastSlash = currentPrefix.lastIndexOf("/");
            if (lastSlash > 0) {
                newPrefix = currentPrefix.substring(0, lastSlash + 1);
            }
        }

        connection.setCurrentPrefix(newPrefix);

        // 重新加载文件列表
        loadBucketFilesForTab(connectionTab);

        // 更新UI状态
        connectionTab.updatePathLabel();
        connectionTab.updateBackButton();
    }

    /// 为指定Tab处理上传
    ///
    public void handleUploadForTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();

        if (connection == null || currentBucket == null) {
            notificationManager.showWarning("请先选择存储桶");
            return;
        }

        javafx.stage.FileChooser fileChooser = new javafx.stage.FileChooser();
        fileChooser.setTitle("选择要上传的文件");

        // 检查批量操作许可证
        if (FeatureGate.isEnabled(Feature.BATCH_OPERATIONS)) {
            // 专业版：支持多文件选择
            java.util.List<java.io.File> files = fileChooser.showOpenMultipleDialog(primaryStage);
            if (files != null && !files.isEmpty()) {
                uploadFilesForTab(connectionTab, files);
            }
        } else {
            // 社区版：单文件选择
            java.io.File file = fileChooser.showOpenDialog(primaryStage);
            if (file != null) {
                uploadFilesForTab(connectionTab, java.util.List.of(file));
            }
        }
    }

    /// 为指定Tab上传文件
    ///
    private void uploadFilesForTab(ConnectionTab connectionTab, java.util.List<java.io.File> files) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();

        if (files == null || files.isEmpty()) return;

        String currentPrefix = connection.getCurrentPrefix();
        long totalSize = files.stream().mapToLong(java.io.File::length).sum();
        boolean isFirstTask = true;

        for (java.io.File file : files) {
            String objectKey = (currentPrefix != null ? currentPrefix : "") + file.getName();
            String description = files.size() == 1
                    ? "上传文件: " + file.getName()
                    : "批量上传: " + file.getName();

            List<String> targetFiles = List.of(file.getName());

            String taskId = taskManager.submitUploadTask(
                    description,
                    connection.getId(),
                    currentBucket,
                    targetFiles,
                    () -> {
                        // 在任务执行时动态获取ProgressTracker
                        StorageTask currentTask = taskManager.getCurrentTask();
                        if (currentTask != null && currentTask.getProgressTracker() != null) {
                            connection.getService().uploadFileWithProgress(
                                    currentBucket,
                                    objectKey,
                                    file,
                                    currentTask.getProgressTracker()
                            );
                        } else {
                            // 作为后备，使用没有进度跟踪的上传
                            connection.getService().uploadFile(currentBucket, objectKey, file);
                        }
                        return null;
                    },
                    file.length()
            );

            // 每创建一个任务就立即显示
            if (taskId != null && isFirstTask) {
                progressDialog.showAllActiveTasks();
                if (files.size() > 1) {
                    // 显示批量上传通知
                    notificationManager.showInfo(String.format("已开始批量上传 %d 个文件 (总大小: %s)",
                            files.size(), FileUtils.formatSize(totalSize)));
                }
                isFirstTask = false;
            }
        }
    }

    /// 为指定Tab处理下载
    ///
    public void handleDownloadForTab(ConnectionTab connectionTab) {
        var selectedObjects = connectionTab.getFileTableView().getSelectionModel().getSelectedItems();
        if (selectedObjects.isEmpty()) {
            notificationManager.showWarning("请先选择要下载的文件");
            return;
        }

        // 过滤掉文件夹
        List<StorageObject> filesOnly = selectedObjects.stream()
                .filter(obj -> !obj.isDirectory())
                .toList();

        if (filesOnly.isEmpty()) {
            notificationManager.showWarning("所选项目中没有文件可以下载");
            return;
        }

        // 检查批量操作许可证
        if (filesOnly.size() > 1 && !FeatureGate.isEnabled(Feature.BATCH_OPERATIONS)) {
            // 社区版不支持批量下载
            UpgradeDialog.show(Feature.BATCH_OPERATIONS);
            return;
        }

        javafx.stage.DirectoryChooser directoryChooser = new javafx.stage.DirectoryChooser();
        directoryChooser.setTitle("选择下载目录");
        java.io.File directory = directoryChooser.showDialog(primaryStage);

        if (directory != null) {
            downloadFilesForTab(connectionTab, filesOnly, directory);
        }
    }

    /// 为指定Tab下载文件
    ///
    private void downloadFilesForTab(ConnectionTab connectionTab, List<StorageObject> objects, java.io.File targetDirectory) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();

        if (objects == null || objects.isEmpty()) return;

        long totalSize = objects.stream().mapToLong(StorageObject::size).sum();
        boolean isFirstTask = true;

        for (StorageObject obj : objects) {
            String fileName = obj.name();
            if (fileName.contains("/")) {
                fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
            }

            java.io.File targetFile = FileUtils.getUniqueFile(targetDirectory, fileName);
            String actualFileName = targetFile.getName();
            String description = objects.size() == 1
                    ? "下载文件: " + actualFileName
                    : "批量下载: " + actualFileName;

            List<String> targetFiles = List.of(fileName);

            String taskId = taskManager.submitDownloadTask(
                    description,
                    connection.getId(),
                    currentBucket,
                    targetFiles,
                    () -> {
                        ProgressTracker tracker = taskManager.getCurrentTask().getProgressTracker();
                        downloadFileWithProgressTracking(
                                connection.getService(),
                                currentBucket,
                                obj.key(),
                                targetFile,
                                tracker
                        );
                        return null;
                    },
                    obj.size()
            );

            // 检查任务是否被限制（社区版任务数限制）
            if (taskId == null) {
                // 社区版已有下载任务在运行，显示升级提示
                UpgradeDialog.show(Feature.TASK_MANAGEMENT);
                return;
            }

            // 每创建一个任务就立即显示
            if (isFirstTask) {
                progressDialog.showAllActiveTasks();
                if (objects.size() > 1) {
                    // 显示批量下载通知
                    notificationManager.showInfo(String.format("已开始批量下载 %d 个文件 (总大小: %s)",
                            objects.size(), FileUtils.formatSize(totalSize)));
                }
                isFirstTask = false;
            }
        }
    }

    /// 为指定Tab处理删除
    ///
    public void handleDeleteForTab(ConnectionTab connectionTab) {
        var selectedItems = connectionTab.getFileTableView().getSelectionModel().getSelectedItems();
        if (selectedItems.isEmpty()) {
            notificationManager.showWarning("请先选择要删除的项目");
            return;
        }

        // 确认对话框
        boolean confirmed = DialogUtils.showConfirmationDialog(
                "确认删除",
                "确定要删除选中的项目吗？",
                "将删除 " + selectedItems.size() + " 个项目，此操作不可撤销。"
        );

        if (confirmed) {
            deleteObjectsForTab(connectionTab, new java.util.ArrayList<>(selectedItems));
        }
    }

    /// 为指定Tab删除对象
    ///
    private void deleteObjectsForTab(ConnectionTab connectionTab, java.util.List<StorageObject> objects) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();

        executeAsyncTask(
                "正在删除 " + objects.size() + " 个项目...",
                () -> {
                    java.util.List<String> keys = objects.stream().map(StorageObject::key).toList();
                    connection.getService().deleteObjects(currentBucket, keys);
                    return null;
                },
                result -> {
                    statusLabel.setText("删除完成");
                    notificationManager.showSuccess("成功删除 " + objects.size() + " 个项目");
                    loadBucketFilesForTab(connectionTab);
                },
                exception -> {
                    statusLabel.setText("删除失败");
                    notificationManager.handleStorageException(exception, "删除项目");
                }
        );
    }

    /// 为指定Tab处理新建文件夹
    ///
    public void handleNewFolderForTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();

        if (connection == null || currentBucket == null) {
            notificationManager.showWarning("请先选择存储桶");
            return;
        }

        Optional<String> result = DialogUtils.showTextInputDialog(
                "新建文件夹",
                null,  // 不使用header，避免两行文字
                "文件夹名称："
        );
        result.ifPresent(folderName -> {
            if (folderName.trim().isEmpty()) {
                notificationManager.showWarning("文件夹名称不能为空");
                return;
            }
            createFolderForTab(connectionTab, folderName.trim());
        });
    }

    /// 为指定Tab创建文件夹
    ///
    private void createFolderForTab(ConnectionTab connectionTab, String folderName) {
        StorageConnection connection = connectionTab.getConnection();
        String currentBucket = connectionTab.getCurrentBucket();
        String currentPrefix = connection.getCurrentPrefix();
        String folderKey = (currentPrefix != null ? currentPrefix : "") + folderName;

        executeAsyncTask(
                "正在创建文件夹: " + folderName,
                () -> {
                    connection.getService().createFolder(currentBucket, folderKey);
                    return null;
                },
                result -> {
                    statusLabel.setText("文件夹创建成功: " + folderName);
                    notificationManager.showSuccess("文件夹创建成功: " + folderName);
                    loadBucketFilesForTab(connectionTab);
                },
                exception -> {
                    statusLabel.setText("文件夹创建失败: " + folderName);
                    notificationManager.handleStorageException(exception, "创建文件夹");
                }
        );
    }

    /// 为指定Tab处理刷新
    ///
    public void handleRefreshForTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();

        if (connection == null) {
            notificationManager.showWarning("没有活动连接");
            return;
        }

        String currentBucket = connectionTab.getCurrentBucket();
        if (currentBucket != null) {
            // 刷新当前存储桶的文件列表
            loadBucketFilesForTab(connectionTab);
        } else {
            // 刷新存储桶列表
            loadBucketsForConnectionTab(connectionTab);
        }
    }

    /// 为指定Tab加载存储桶列表
    ///
    private void loadBucketsForConnectionTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();

        if (!connection.isConnected()) return;

        executeAsyncTask(
                "正在加载存储桶列表...",
                () -> connection.getService().listBuckets(),
                buckets -> {
                    connectionTab.getAvailableBuckets().setAll(
                            buckets.stream()
                                    .map(StorageBucket::name)
                                    .toList()
                    );
                    connectionTab.getBucketComboBox().setDisable(false);
                    statusLabel.setText("已加载 " + buckets.size() + " 个存储桶");
                },
                exception -> {
                    statusLabel.setText("加载存储桶失败: " + exception.getMessage());
                    connectionTab.getBucketComboBox().setDisable(true);
                    notificationManager.handleStorageException(exception, "加载存储桶列表");
                }
        );
    }

    /// 刷新指定Tab的存储桶列表
    ///
    public void refreshBucketsForTab(ConnectionTab connectionTab) {
        StorageConnection connection = connectionTab.getConnection();

        if (!connection.isConnected()) return;

        // 保存当前选中的存储桶
        String currentBucket = connectionTab.getCurrentBucket();

        executeAsyncTask(
                "正在刷新存储桶列表...",
                () -> connection.getService().listBuckets(),
                buckets -> {
                    connectionTab.getAvailableBuckets().setAll(
                            buckets.stream()
                                    .map(StorageBucket::name)
                                    .toList()
                    );

                    // 尝试恢复之前选中的存储桶
                    if (currentBucket != null && connectionTab.getAvailableBuckets().contains(currentBucket)) {
                        connectionTab.getBucketComboBox().setValue(currentBucket);
                    }

                    connectionTab.getBucketComboBox().setDisable(false);
                    statusLabel.setText("已刷新存储桶列表，共 " + buckets.size() + " 个存储桶");
                    notificationManager.showSuccess("存储桶列表已刷新");
                },
                exception -> {
                    statusLabel.setText("刷新存储桶失败: " + exception.getMessage());
                    notificationManager.handleStorageException(exception, "刷新存储桶列表");
                }
        );
    }

    /// 创建左侧面板（存储树视图）
    ///
    private VBox createLeftPanel() {
        VBox leftPanel = new VBox();
        leftPanel.setSpacing(5);
        leftPanel.setPadding(new Insets(5));

        // 标题
        Label titleLabel = new Label("存储连接");
        titleLabel.getStyleClass().add("title");

        // 创建存储树视图
        storageTreeView = createStorageTreeView();

        // 移除通知区域显示，保留notificationArea变量但不添加到界面
        if (notificationArea == null) {
            notificationArea = new VBox();
            notificationArea.setSpacing(5);
            notificationArea.setPadding(new Insets(5));
        }
        notificationArea.setPrefWidth(100);

        leftPanel.getChildren().addAll(titleLabel, storageTreeView);
        VBox.setVgrow(storageTreeView, Priority.ALWAYS);

        return leftPanel;
    }


    /// 创建存储树视图
    ///
    private TreeView<TreeNodeData> createStorageTreeView() {
        // 创建根节点
        treeRootItem = new TreeItem<>(new TreeNodeData("存储服务"));
        treeRootItem.setExpanded(true);

        // 创建树视图
        TreeView<TreeNodeData> treeView = new TreeView<>(treeRootItem);
        treeView.setShowRoot(false);

        // 设置自定义单元格工厂，显示图标
        treeView.setCellFactory(tree -> new TreeCell<TreeNodeData>() {
            @Override
            protected void updateItem(TreeNodeData item, boolean empty) {
                super.updateItem(item, empty);
                if (empty || item == null) {
                    setText(null);
                    setGraphic(null);
                } else {
                    String icon = getTreeNodeIcon(item);
                    String displayText = getTreeNodeDisplayText(item);
                    setText(icon + " " + displayText);
                }
            }
        });

        // 设置双击事件处理连接
        treeView.setOnMouseClicked(event -> {
            if (event.getClickCount() == 2) {
                TreeItem<TreeNodeData> selectedItem = treeView.getSelectionModel().getSelectedItem();
                handleTreeDoubleClick(selectedItem);
            }
        });

        // 设置单击选择事件（仅用于UI状态更新，不触发连接）
        treeView.getSelectionModel().selectedItemProperty().addListener((observable, oldItem, newItem) ->
                handleTreeSelection(newItem)
        );

        // 设置右键菜单
        treeView.setOnContextMenuRequested(event -> {
            TreeItem<TreeNodeData> selectedItem = treeView.getSelectionModel().getSelectedItem();
            if (selectedItem != null && selectedItem.getValue().isConnection()) {
                TreeNodeData nodeData = selectedItem.getValue();
                StorageConnection connection = nodeData.getConnection();

                // 只有保存的连接才能编辑
                if (connection.getDisplayName() != null && !connection.getDisplayName().trim().isEmpty()) {
                    showConnectionContextMenu(event.getScreenX(), event.getScreenY(), connection);
                }
            }
        });

        return treeView;
    }

    /// 获取树节点对应的图标
    ///
    private String getTreeNodeIcon(TreeNodeData nodeData) {
        return switch (nodeData.getNodeType()) {
            case ROOT -> "🏠";
            case STORAGE_TYPE -> getStorageTypeIcon(nodeData.getStorageType());
            case CONNECTION -> nodeData.getConnection().isConnected() ? "🔗" : "🔌";
            case BUCKET -> FileIconManager.FOLDER_ICON;
        };
    }

    /// 获取存储类型对应的图标
    ///
    private String getStorageTypeIcon(StorageType storageType) {
        return switch (storageType) {
            case MINIO -> "📦";
            case ALIYUN_OSS -> "☁️";
            case TENCENT_COS -> "🏢";
            case HUAWEI_OBS -> "📡";
            case QINIU_KODO -> "🌐";
            case BAIDU_BOS -> "🔍";
            case VOLC_ENGINE_TOS -> "🌋";
        };
    }

    /// 获取树节点的显示文本
    ///
    private String getTreeNodeDisplayText(TreeNodeData nodeData) {
        if (nodeData.isConnection()) {
            StorageConnection connection = nodeData.getConnection();
            String baseName = connection.getDisplayName();

            // 如果是保存的连接且未连接，添加 (已保存) 标识
            if (connection.isSavedConnection() && !connection.isConnected()) {
                return baseName + " (已保存)";
            }

            // 其他情况返回连接状态信息
            return baseName + " [" + (connection.isConnected() ? "已连接" : "未连接") + "]";
        }

        // 对于非连接节点，使用原始的toString
        return nodeData.getDisplayText();
    }


    /// 处理树选择事件（仅用于切换Tab）
    ///
    private void handleTreeSelection(TreeItem<TreeNodeData> selectedItem) {
        if (selectedItem == null) return;

        TreeNodeData nodeData = selectedItem.getValue();
        if (nodeData.isConnection()) {
            StorageConnection connection = nodeData.getConnection();

            // 如果连接已连接且有对应的Tab，切换到该Tab
            if (connection.isConnected()) {
                String connectionId = connection.getId();
                Tab tab = connectionTabs.get(connectionId);
                if (tab != null) {
                    connectionTabPane.getSelectionModel().select(tab);
                }
            }
        }
    }

    /// 处理树双击事件（触发连接操作）
    ///
    private void handleTreeDoubleClick(TreeItem<TreeNodeData> selectedItem) {
        if (selectedItem == null) return;

        TreeNodeData nodeData = selectedItem.getValue();
        if (nodeData.isConnection()) {
            StorageConnection connection = nodeData.getConnection();

            // 如果连接已打开，不处理
            if (connection.isConnected()) {
                return;
            }

            // 检查是否为已保存但未连接的连接
            if (connection.isSavedConnection()) {
                // 显示密钥输入对话框并连接
                showSavedConnectionPasswordDialog(connection);
            }
            // 注意：非保存的未连接连接不能通过双击连接，它们只能通过新建连接对话框创建和连接
        }
    }

    /// 通用异步任务执行方法
    ///
    private <T> void executeAsyncTask(
            String loadingMessage,
            java.util.concurrent.Callable<T> taskCallable,
            java.util.function.Consumer<T> onSuccess,
            java.util.function.Consumer<Exception> onFailure) {

        statusLabel.setText(loadingMessage);

        Task<T> task = new Task<T>() {
            @Override
            protected T call() throws Exception {
                return taskCallable.call();
            }

            @Override
            protected void succeeded() {
                Platform.runLater(() -> onSuccess.accept(getValue()));
            }

            @Override
            protected void failed() {
                Platform.runLater(() -> onFailure.accept((Exception) getException()));
            }
        };

        // 使用TaskManager的线程池而不是直接创建Thread
        taskManager.submitTask(task);
    }

    /// 创建底部状态栏
    ///
    private HBox createStatusBar() {
        HBox statusBar = new HBox();
        statusBar.setSpacing(10);
        statusBar.setPadding(new Insets(5));
        statusBar.setStyle("-fx-background-color: #f0f0f0; -fx-border-color: #ccc; -fx-border-width: 1 0 0 0;");

        // 左侧：网站链接区域
        docLabel = new Label("官方文档：");
        docLabel.setStyle("-fx-font-size: 12px; -fx-text-fill: #666;");
        docLabel.setVisible(false); // 初始时隐藏

        websiteLabel = new Label("");
        websiteLabel.setStyle("-fx-text-fill: blue; -fx-underline: true; -fx-cursor: hand; -fx-font-size: 12px;");
        websiteLabel.setOnMouseClicked(e -> {
            if (!websiteLabel.getText().isEmpty()) {
                openWebsite(websiteLabel.getText());
            }
        });
        websiteLabel.setVisible(false); // 初始时隐藏

        // 左侧区域
        HBox leftArea = new HBox(5);
        leftArea.getChildren().addAll(docLabel, websiteLabel);
        leftArea.setAlignment(Pos.CENTER_LEFT);

        // 中间：状态信息
        statusLabel = new Label("就绪");
        statusLabel.setStyle("-fx-alignment: center;");

        // 中间区域（可伸展）
        HBox centerArea = new HBox();
        centerArea.getChildren().add(statusLabel);
        centerArea.setAlignment(Pos.CENTER);
        HBox.setHgrow(centerArea, Priority.ALWAYS);

        // 右侧：错误按钮和版本信息
        Button errorButton = new Button();
        errorButton.getStyleClass().add("error-button");
        errorButton.setVisible(false); // 初始隐藏

        HBox rightArea = new HBox(10);
        rightArea.getChildren().addAll(errorButton);
        rightArea.setAlignment(Pos.CENTER_RIGHT);

        statusBar.getChildren().addAll(leftArea, centerArea, rightArea);

        // 设置错误按钮到通知管理器
        notificationManager.setErrorButton(errorButton);

        return statusBar;
    }

    /// 打开网站
    ///
    private void openWebsite(String url) {
        try {
            java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
        } catch (Exception e) {
            notificationManager.showError("无法打开网站: " + e.getMessage());
        }
    }

    /// 设置工具栏事件
    ///
    private void setupToolBarEvents() {
        newConnectionButton.setOnAction(e -> showNewConnectionDialog());
        closeConnectionButton.setOnAction(e -> closeActiveConnection());
        taskManagerButton.setOnAction(e -> showTaskManager());
    }

    /// 显示新建连接对话框
    ///
    private void showNewConnectionDialog() {
        showNewConnectionDialog(null);
    }

    private void showNewConnectionDialog(String errorMessage) {
        // 如果有错误信息，先显示错误
        if (errorMessage != null && !errorMessage.isEmpty()) {
            boolean retry = DialogUtils.showErrorWithRetryDialog(
                    "连接失败",
                    "连接存储服务失败",
                    errorMessage
            );
            if (!retry) {
                return;
            }
        }

        ConnectionDialog dialog = new ConnectionDialog();
        Optional<ConnectionResult> result = dialog.showAndWait();

        result.ifPresent(connectionResult -> {
            StorageConfig config = connectionResult.config();
            String displayName = connectionResult.displayName();

            // 如果是保存的连接且名称已存在，先移除旧的同名连接
            if (displayName != null && !displayName.trim().isEmpty()) {
                removeExistingSavedConnection(displayName.trim());
            }

            // 添加到连接管理器
            String connectionId = connectionManager.addConnection(config, displayName);
            StorageConnection connection = connectionManager.getConnection(connectionId);

            // 如果用户填写了连接名称，标记为已保存的连接并保存密钥
            if (displayName != null && !displayName.trim().isEmpty()) {
                connection.setSavedConnection(true);

                // 将密钥保存到 CredentialManager
                try {
                    CredentialManager credentialManager = CredentialManager.getInstance();
                    credentialManager.saveCredentials(
                            displayName.trim(),
                            config.endpoint(),
                            config.accessKey(),
                            config.secretKey(),
                            config.region()
                    );
                    notificationManager.showInfo("连接配置和密钥已安全保存");
                } catch (Exception e) {
                    notificationManager.showWarning("连接配置已保存，但密钥保存失败: " + e.getMessage());
                }
            }

            // 连接到存储服务
            connectToStorage(connection);
        });
    }

    /// 移除已存在的同名保存连接
    ///
    private void removeExistingSavedConnection(String connectionName) {
        // 查找并移除同名的保存连接
        StorageConnection existingConnection = null;
        for (StorageConnection connection : connectionManager.getAllConnections()) {
            if (connection.isSavedConnection() &&
                    connection.getDisplayName().equals(connectionName)) {
                existingConnection = connection;
                break;
            }
        }

        if (existingConnection != null) {
            // 从树视图中移除
            removeConnectionFromTree(existingConnection);
            // 断开连接
            existingConnection.disconnect();
            // 从连接管理器中移除
            connectionManager.removeConnection(existingConnection.getId());
        }
    }

    /// 连接到存储服务
    ///
    private void connectToStorage(StorageConnection connection) {
        // 检查活动连接数限制（社区版：最多2个同时打开的连接）
        if (!connectionManager.canOpenMoreConnections()) {
            // 超出活动连接数限制，显示升级对话框
            UpgradeDialog.show(Feature.UNLIMITED_CONNECTIONS);

            // 如果不是保存的连接，从管理器中移除
            if (!connection.isSavedConnection()) {
                connectionManager.removeConnection(connection.getId());
            }
            return;
        }

        statusLabel.setText("正在连接：" + connection.getDisplayName() + "...");

        Task<Void> connectTask = new Task<>() {
            @Override
            protected Void call() {
                // 创建存储服务
                ObjectStorageService service = StorageServiceFactory.createService(connection.getConfig().type());
                service.connect(connection.getConfig());

                // 测试连接 - 尝试列出buckets
                var buckets = service.listBuckets();

                // 设置服务和连接状态
                connection.setService(service);
                connection.setConnected(true);

                Platform.runLater(() -> {
                    // 添加到树视图
                    addConnectionToTree(connection, buckets);

                    // 创建连接Tab
                    createConnectionTab(connection);

                    statusLabel.setText("已连接：" + connection.getDisplayName());
                    notificationManager.showSuccess("成功连接：" + connection.getDisplayName());
                    updateUI();
                });

                return null;
            }

            @Override
            protected void failed() {
                Platform.runLater(() -> {
                    // 连接失败处理
                    connection.disconnect();

                    // 如果是保存的连接，不要删除，只是断开连接
                    if (!connection.isSavedConnection()) {
                        connectionManager.removeConnection(connection.getId());
                    }

                    statusLabel.setText("连接失败");

                    // 记录异常到异常列表
                    Throwable exception = getException();
                    notificationManager.handleStorageException(exception, "连接：" + connection.getDisplayName());

                    // 重新显示连接对话框并显示错误
                    String errorMessage = exception.getMessage();
                    showNewConnectionDialog("连接失败：" + errorMessage);
                });
            }
        };

        // 使用TaskManager的线程池
        taskManager.submitTask(connectTask);
    }

    /// 添加连接到树视图
    ///
    private void addConnectionToTree(StorageConnection connection, java.util.List<StorageBucket> buckets) {
        StorageType storageType = connection.getConfig().type();

        // 查找或创建存储类型节点
        TreeItem<TreeNodeData> storageTypeItem = findOrCreateStorageTypeNode(storageType);

        // 创建连接节点（不再添加存储桶子节点）
        TreeNodeData connectionNodeData = new TreeNodeData(connection);
        TreeItem<TreeNodeData> connectionItem = new TreeItem<>(connectionNodeData);

        // 将连接节点添加到存储类型节点下
        storageTypeItem.getChildren().add(connectionItem);
        storageTypeItem.setExpanded(true);

        // 选中新添加的连接节点
        storageTreeView.getSelectionModel().select(connectionItem);
    }

    /// 查找或创建存储类型节点
    ///
    private TreeItem<TreeNodeData> findOrCreateStorageTypeNode(StorageType storageType) {
        // 查找现有的存储类型节点
        for (TreeItem<TreeNodeData> child : treeRootItem.getChildren()) {
            TreeNodeData childData = child.getValue();
            if (childData.isStorageType() && childData.getStorageType() == storageType) {
                return child;
            }
        }

        // 创建新的存储类型节点
        TreeNodeData storageTypeNodeData = new TreeNodeData(storageType);
        TreeItem<TreeNodeData> storageTypeItem = new TreeItem<>(storageTypeNodeData);
        treeRootItem.getChildren().add(storageTypeItem);
        storageTypeItem.setExpanded(true);

        return storageTypeItem;
    }


    /// 关闭活动连接
    ///
    private void closeActiveConnection() {
        if (activeConnection == null) {
            return;
        }

        // 保存连接引用，防止在操作过程中被其他事件清空
        StorageConnection connectionToClose = activeConnection;

        // 显示确认对话框
        boolean confirmed = DialogUtils.showConfirmationDialog(
                "关闭连接",
                "确定要关闭连接吗？",
                "关闭连接: " + connectionToClose.getDisplayName()
        );

        if (confirmed) {
            // 关闭对应的Tab页签
            String connectionId = connectionToClose.getId();
            Tab connectionTab = connectionTabs.get(connectionId);
            if (connectionTab != null) {
                connectionTabPane.getTabs().remove(connectionTab);
                connectionTabs.remove(connectionId);
                connectionTabContents.remove(connectionId);
            }

            // 检查是否为保存的连接
            if (connectionToClose.isSavedConnection()) {
                // 保存的连接：只断开连接，不从列表中移除
                connectionToClose.disconnect();
                connectionToClose.setSavedConnection(true); // 重新标记为保存状态

                // 更新树视图中的显示名称，添加"(已保存)"标识
                updateSavedConnectionDisplayName(connectionToClose);

                notificationManager.showInfo("已断开连接，连接已保留在列表中");
            } else {
                // 普通连接：完全移除
                removeConnectionFromTree(connectionToClose);
                connectionToClose.disconnect();
                connectionManager.removeConnection(connectionToClose.getId());

                notificationManager.showInfo("已断开连接");
            }

            // 清空当前状态
            activeConnection = null;
            activeBucket = null;

            updateUI();
        }
    }

    /// 更新保存连接的显示名称
    ///
    private void updateSavedConnectionDisplayName(StorageConnection connection) {
        // 刷新树视图以更新显示状态
        // 由于TreeView使用了自定义的图标逻辑，状态改变后会自动更新显示
        for (TreeItem<TreeNodeData> storageTypeItem : treeRootItem.getChildren()) {
            for (TreeItem<TreeNodeData> connectionItem : storageTypeItem.getChildren()) {
                TreeNodeData connectionData = connectionItem.getValue();
                if (connectionData.isConnection() && connectionData.getConnection().equals(connection)) {
                    // 触发TreeView刷新这个节点
                    connectionItem.setValue(connectionData); // 重新设置值以触发刷新
                    return;
                }
            }
        }
    }

    /// 从树视图中移除连接
    ///
    private void removeConnectionFromTree(StorageConnection connection) {
        for (TreeItem<TreeNodeData> storageTypeItem : treeRootItem.getChildren()) {
            for (TreeItem<TreeNodeData> connectionItem : storageTypeItem.getChildren()) {
                TreeNodeData connectionData = connectionItem.getValue();
                if (connectionData.isConnection() && connectionData.getConnection().equals(connection)) {
                    storageTypeItem.getChildren().remove(connectionItem);

                    // 如果存储类型节点下没有连接了，移除存储类型节点
                    if (storageTypeItem.getChildren().isEmpty()) {
                        treeRootItem.getChildren().remove(storageTypeItem);
                    }
                    return;
                }
            }
        }
    }


    /// 显示任务管理器
    ///
    private void showTaskManager() {
        progressDialog.showAllActiveTasks();
    }


    /// 显示已保存连接的密钥输入对话框
    ///
    private void showSavedConnectionPasswordDialog(StorageConnection savedConnection) {
        // 首先尝试从 CredentialManager 加载已保存的密钥
        CredentialManager credentialManager = CredentialManager.getInstance();
        CredentialManager.StoredCredential storedCredential = credentialManager.loadCredentials(savedConnection.getDisplayName());

        if (storedCredential != null) {
            // 找到了保存的密钥，直接连接
            statusLabel.setText("找到已保存的密钥，正在连接...");
            notificationManager.showInfo("使用已保存的密钥连接: " + savedConnection.getDisplayName());

            StorageConfig completeConfig = new StorageConfig(
                    savedConnection.getConfig().type(),
                    storedCredential.getEndpoint(),
                    storedCredential.getAccessKey(),
                    storedCredential.getSecretKey(), // 使用已保存的密钥
                    storedCredential.getRegion(),
                    savedConnection.getConfig().useSSL(),
                    null
            );

            // 直接连接到存储服务
            connectToSavedConnection(savedConnection, completeConfig);
            return;
        }

        // 没有找到保存的密钥，要求用户输入
        // 创建密钥输入对话框
        Dialog<String> dialog = new Dialog<>();
        dialog.setTitle("连接");
        dialog.setHeaderText("连接: " + savedConnection.getDisplayName() + "\n(未找到保存的密钥，请输入)");

        // 设置按钮类型
        ButtonType connectButtonType = new ButtonType("连接", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(connectButtonType, ButtonType.CANCEL);

        // 创建输入控件
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        PasswordField passwordField = new PasswordField();
        passwordField.setPromptText("请输入密钥");
        passwordField.setPrefWidth(250);

        grid.add(new Label("密钥:"), 0, 0);
        grid.add(passwordField, 1, 0);

        // 启用/禁用连接按钮
        Button connectButton = (Button) dialog.getDialogPane().lookupButton(connectButtonType);
        connectButton.disableProperty().bind(passwordField.textProperty().isEmpty());

        dialog.getDialogPane().setContent(grid);

        // 设置焦点
        Platform.runLater(passwordField::requestFocus);

        // 设置结果转换器
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == connectButtonType) {
                return passwordField.getText();
            }
            return null;
        });

        // 显示对话框并处理结果
        Optional<String> result = dialog.showAndWait();
        result.ifPresent(password -> {
            // 创建包含密钥的完整配置
            StorageConfig completeConfig = new StorageConfig(
                    savedConnection.getConfig().type(),
                    savedConnection.getConfig().endpoint(),
                    savedConnection.getConfig().accessKey(),
                    password, // 用户输入的密钥
                    savedConnection.getConfig().region(),
                    savedConnection.getConfig().useSSL(),
                    null
            );

            // 连接到存储服务
            connectToSavedConnection(savedConnection, completeConfig);
        });
    }

    /// 连接到已保存的存储连接
    ///
    private void connectToSavedConnection(StorageConnection savedConnection, StorageConfig completeConfig) {
        // 检查活动连接数限制（社区版：最多2个同时打开的连接）
        if (!connectionManager.canOpenMoreConnections()) {
            // 超出活动连接数限制，显示升级对话框
            UpgradeDialog.show(Feature.UNLIMITED_CONNECTIONS);
            return;
        }

        statusLabel.setText("正在连接到：" + savedConnection.getDisplayName() + "...");

        Task<Void> connectTask = new Task<>() {
            @Override
            protected Void call() {
                // 创建存储服务
                ObjectStorageService service = StorageServiceFactory.createService(completeConfig.type());
                service.connect(completeConfig);

                // 测试连接 - 尝试列出buckets
                service.listBuckets();

                // 设置服务和连接状态
                savedConnection.setService(service);
                savedConnection.setConnected(true);
                // 保持作为已保存连接的状态

                Platform.runLater(() -> {
                    statusLabel.setText("已连接到 " + savedConnection.getDisplayName());
                    notificationManager.showSuccess("成功连接到保存的连接: " + savedConnection.getDisplayName());

                    // 创建连接Tab
                    createConnectionTab(savedConnection);

                    // 刷新树视图以更新连接状态显示
                    // 直接刷新整个树视图，让CellFactory重新计算所有显示文本
                    // 这样可以确保getTreeNodeDisplayText方法被调用
                    storageTreeView.refresh();

                    updateUI();
                });

                return null;
            }

            @Override
            protected void failed() {
                Platform.runLater(() -> {
                    statusLabel.setText("连接失败");

                    // 记录异常到异常列表
                    Throwable exception = getException();
                    notificationManager.handleStorageException(exception, "连接“" + savedConnection.getDisplayName() + "”");

                    // 可以选择重新显示密钥输入对话框
                    String errorMessage = exception.getMessage();
                    boolean retry = DialogUtils.showErrorWithRetryDialog(
                            "连接失败",
                            "连接失败",
                            errorMessage
                    );
                    if (retry) {
                        showSavedConnectionPasswordDialog(savedConnection);
                    }
                });
            }
        };

        // 使用TaskManager的线程池
        taskManager.submitTask(connectTask);
    }

    /// 通用的文件下载进度跟踪方法 - 适用于所有存储服务
    /// 这样进度跟踪逻辑在业务层，而不是存储服务层
    ///
    private void downloadFileWithProgressTracking(
            ObjectStorageService storageService,
            String bucketName,
            String objectKey,
            java.io.File localFile,
            ProgressTracker progressTracker) throws Exception {

        // 创建临时文件
        java.io.File tempFile = new java.io.File(localFile.getAbsolutePath() + ".tmp." + System.currentTimeMillis());

        try {
            // 从存储服务获取InputStream - 这是存储服务应该提供的
            try (java.io.InputStream inputStream = storageService.downloadFile(bucketName, objectKey);
                 java.io.FileOutputStream fos = new java.io.FileOutputStream(tempFile);
                 java.io.BufferedOutputStream bufferedOutput = new java.io.BufferedOutputStream(fos, 64 * 1024)) {

                // 在业务层处理进度跟踪
                byte[] buffer = new byte[64 * 1024];
                int bytesRead;
                long totalBytesRead = 0;
                long lastReportedBytes = 0;
                final long reportInterval = 256 * 1024; // 每256KB报告一次进度

                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    if (progressTracker.isCancelled()) {
                        throw new RuntimeException("下载已被用户取消");
                    }

                    bufferedOutput.write(buffer, 0, bytesRead);
                    totalBytesRead += bytesRead;

                    // 定期更新进度
                    if (totalBytesRead - lastReportedBytes >= reportInterval) {
                        progressTracker.addProcessedBytes(totalBytesRead - lastReportedBytes);
                        lastReportedBytes = totalBytesRead;
                    }
                }

                // 最终进度更新
                if (totalBytesRead > lastReportedBytes) {
                    progressTracker.addProcessedBytes(totalBytesRead - lastReportedBytes);
                }
            }

            // 原子性移动临时文件到最终位置
            if (localFile.exists()) {
                java.nio.file.Files.delete(localFile.toPath());
            }
            java.nio.file.Files.move(tempFile.toPath(), localFile.toPath());

        } catch (Exception e) {
            // 清理临时文件
            if (tempFile.exists()) {
                try {
                    java.nio.file.Files.delete(tempFile.toPath());
                } catch (Exception deleteEx) {
                    // 忽略删除异常
                }
            }
            throw e;
        }
    }

    /// 更新UI状态
    ///
    private void updateUI() {
        boolean hasActiveConnection = activeConnection != null && activeConnection.isConnected();
        closeConnectionButton.setDisable(!hasActiveConnection);

        // 更新状态栏
        if (hasActiveConnection) {
            if (activeBucket != null) {
                statusLabel.setText("当前: " + activeConnection.getDisplayName() + " / " + activeBucket);
            } else {
                statusLabel.setText("当前连接: " + activeConnection.getDisplayName());
            }

            // 更新网站链接
            if (activeConnection.getConfig() != null && activeConnection.getConfig().type() != null) {
                String websiteUrl = activeConnection.getConfig().type().getWebsiteUrl();
                websiteLabel.setText(websiteUrl);
                websiteLabel.setVisible(true);
                docLabel.setVisible(true);
            } else {
                websiteLabel.setVisible(false);
                docLabel.setVisible(false);
            }
        } else {
            statusLabel.setText("无活动连接");
            websiteLabel.setVisible(false);
            docLabel.setVisible(false);
        }
    }

    /// 加载已保存的连接到连接管理器
    ///
    private void loadSavedConnections() {
        try {
            ConfigManager configManager = new ConfigManager();
            List<ConfigManager.SavedConnection> savedConnections = configManager.loadAllConnections();

            for (ConfigManager.SavedConnection savedConnection : savedConnections) {
                // 创建一个占位的StorageConfig（不包含密钥）
                StorageConfig config = new StorageConfig(
                        savedConnection.type,
                        savedConnection.endpoint,
                        savedConnection.accessKey,
                        "", // 密钥为空，需要用户输入
                        savedConnection.region,
                        savedConnection.useSSL,
                        null
                );

                // 添加到连接管理器（但不连接）
                String connectionId = connectionManager.addConnection(config, savedConnection.name);
                StorageConnection connection = connectionManager.getConnection(connectionId);

                // 标记为已保存的连接（不自动连接）
                connection.setSavedConnection(true);

                // 添加到树视图但不连接
                addSavedConnectionToTree(connection);
            }

            if (!savedConnections.isEmpty()) {
                notificationManager.showInfo("已加载 " + savedConnections.size() + " 个保存的连接");
            }

        } catch (Exception e) {
            System.err.println("Failed to load saved connections: " + e.getMessage());
        }
    }

    /// 添加已保存的连接到树视图（不连接状态）
    ///
    private void addSavedConnectionToTree(StorageConnection connection) {
        StorageType storageType = connection.getConfig().type();

        // 查找或创建存储类型节点
        TreeItem<TreeNodeData> storageTypeItem = findOrCreateStorageTypeNode(storageType);

        // 创建连接节点
        TreeNodeData connectionNodeData = new TreeNodeData(connection);
        TreeItem<TreeNodeData> connectionItem = new TreeItem<>(connectionNodeData);

        // 将连接节点添加到存储类型节点下
        storageTypeItem.getChildren().add(connectionItem);
        storageTypeItem.setExpanded(true);
    }

    /// 显示连接的右键菜单
    ///
    private void showConnectionContextMenu(double screenX, double screenY, StorageConnection connection) {
        ContextMenu contextMenu = new ContextMenu();

        // 编辑连接菜单项
        MenuItem editItem = new MenuItem("编辑连接");
        editItem.setOnAction(e -> editConnection(connection));
        contextMenu.getItems().add(editItem);

        // 删除连接菜单项（仅针对保存的连接）
        MenuItem deleteItem = new MenuItem("删除连接");
        deleteItem.setOnAction(e -> deleteConnection(connection));
        contextMenu.getItems().add(deleteItem);

        contextMenu.show(primaryStage, screenX, screenY);
    }

    /// 编辑连接
    ///
    private void editConnection(StorageConnection connection) {
        ConfigManager configManager = new ConfigManager();
        ConfigManager.SavedConnection savedConnection = configManager.findConnectionByName(connection.getDisplayName());

        if (savedConnection != null) {
            ConnectionDialog dialog = new ConnectionDialog(savedConnection);
            Optional<ConnectionResult> result = dialog.showAndWait();

            if (result.isPresent()) {
                ConnectionResult connectionResult = result.get();

                // 如果连接名称发生变化，需要更新UI
                if (!connection.getDisplayName().equals(connectionResult.displayName())) {
                    refreshStorageTree();
                }

                notificationManager.showSuccess("连接已更新: " + connectionResult.displayName());
            }
        } else {
            notificationManager.showError("未找到保存的连接配置");
        }
    }

    /// 删除连接
    ///
    private void deleteConnection(StorageConnection connection) {
        Alert confirmAlert = new Alert(Alert.AlertType.CONFIRMATION);
        confirmAlert.setTitle("确认删除");
        confirmAlert.setHeaderText("删除连接配置");
        confirmAlert.setContentText("确定要删除连接 \"" + connection.getDisplayName() + "\" 吗？\n此操作不可撤销。");

        Optional<ButtonType> result = confirmAlert.showAndWait();
        if (result.isPresent() && result.get() == ButtonType.OK) {
            ConfigManager configManager = new ConfigManager();
            configManager.deleteConnection(connection.getDisplayName());

            // 如果连接正在使用，先断开连接
            if (connection.isConnected()) {
                connection.disconnect();
                connectionManager.removeConnection(connection.getId());
            }

            // 刷新存储树，移除已删除的连接
            refreshStorageTree();
            notificationManager.showSuccess("连接已删除: " + connection.getDisplayName());
        }
    }

    /// 刷新存储树
    ///
    private void refreshStorageTree() {
        // 清空现有的树结构
        treeRootItem.getChildren().clear();

        // 重新构建存储树
        buildStorageTree();
    }

    /// 构建存储树
    ///
    private void buildStorageTree() {
        loadSavedConnections();
    }
}